<script setup lang="ts">
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { onMounted, onBeforeUnmount } from 'vue';

// 穴位数据
const acupoints = [
  { name: '百会穴', coords: [0, 18, 0], meridian: '督脉' },
  { name: '膻中穴', coords: [0, 13, 2], meridian: '任脉' },
  { name: '中府穴', coords: [3, 12, 2], meridian: '肺经' },
  { name: '曲池穴', coords: [6, 8, 0], meridian: '大肠经' },
  { name: '足三里', coords: [3, -8, 2], meridian: '胃经' },
  // ... 可以添加更多穴位
];

// 经络数据 - 定义经络连接的穴位
const meridians = [
  {
    name: '任脉',
    color: 0xff0000,
    points: ['膻中穴', '中府穴']
  },
  {
    name: '督脉',
    color: 0x0000ff,
    points: ['百会穴', '膻中穴']
  },
  // ... 可以添加更多经络
];

let scene: THREE.Scene;
let camera: THREE.PerspectiveCamera;
let renderer: THREE.WebGLRenderer;
let controls: OrbitControls;
let labelRenderer: CSS2DRenderer;
let animationFrameId: number;

const init = () => {
  // 场景设置
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0xf0f0f0);

  // 相机设置
  camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );
  camera.position.set(0, 0, 30);

  // 渲染器设置
  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.shadowMap.enabled = true;
  
  const container = document.getElementById('container');
  if (container) {
    container.appendChild(renderer.domElement);
  }

  // 控制器设置
  controls = new OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true;
  controls.dampingFactor = 0.05;

  // 光照设置
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
  scene.add(ambientLight);

  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
  directionalLight.position.set(0, 10, 10);
  directionalLight.castShadow = true;
  scene.add(directionalLight);

  // 加载人体模型
  const loader = new GLTFLoader();
  loader.load('/models/human_model.gltf', (gltf) => {
    const model = gltf.scene;
    model.scale.set(0.5, 0.5, 0.5);
    model.position.set(0, -10, 0);
    scene.add(model);
  });

  // 添加穴位点
  addAcupoints();

  // 添加经络线
  addMeridians();

  // 开始动画循环
  animate();
};

// 添加穴位点和标签
const addAcupoints = () => {
  const geometry = new THREE.SphereGeometry(0.2);
  const material = new THREE.MeshPhongMaterial({ color: 0xff0000 });

  acupoints.forEach(point => {
    const sphere = new THREE.Mesh(geometry, material);
    sphere.position.set(...point.coords);
    scene.add(sphere);

    // 添加穴位标签
    const label = document.createElement('div');
    label.className = 'acupoint-label';
    label.textContent = point.name;
    const labelObject = new CSS2DObject(label);
    labelObject.position.set(...point.coords);
    scene.add(labelObject);
  });
};

// 添加经络线
const addMeridians = () => {
  meridians.forEach(meridian => {
    const points: THREE.Vector3[] = [];
    meridian.points.forEach(pointName => {
      const point = acupoints.find(p => p.name === pointName);
      if (point) {
        points.push(new THREE.Vector3(...point.coords));
      }
    });

    const geometry = new THREE.BufferGeometry().setFromPoints(points);
    const material = new THREE.LineBasicMaterial({
      color: meridian.color,
      linewidth: 2
    });
    const line = new THREE.Line(geometry, material);
    scene.add(line);
  });
};

// 动画循环
const animate = () => {
  animationFrameId = requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
  if (labelRenderer) {
    labelRenderer.render(scene, camera);
  }
};

// 窗口大小调整处理
const handleResize = () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
  if (labelRenderer) {
    labelRenderer.setSize(window.innerWidth, window.innerHeight);
  }
};

// 生命周期钩子
onMounted(() => {
  init();
  window.addEventListener('resize', handleResize);
});

onBeforeUnmount(() => {
  window.removeEventListener('resize', handleResize);
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId);
  }
  // 清理Three.js资源
  scene.traverse((object) => {
    if (object instanceof THREE.Mesh) {
      object.geometry.dispose();
      if (object.material instanceof THREE.Material) {
        object.material.dispose();
      }
    }
  });
  renderer.dispose();
});
</script>

<template>
  <div id="container"></div>
</template>

<style lang="css" scoped>
#container {
  width: 100%;
  height: 100vh;
}

.acupoint-label {
  color: #ffffff;
  padding: 2px 6px;
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.6);
  font-size: 12px;
  pointer-events: none;
  white-space: nowrap;
}
</style>